﻿#define _CRT_SECURE_NO_WARNINGS 1
#include<iostream>

using namespace std;


//template <class T1, class T2>
//struct pair
//{
//	typedef T1 first_type;
//	typedef T2 second_type;
//	T1 first;
//	T2 second;
//	pair() 
//		: first(T1()), second(T2())
//	{}
//	pair(const T1& a, const T2& b)
//		: first(a), second(b)
//	{}
//};

//#include <set>
//void TestSet()
//{
//	// 用数组array中的元素构造set
//	int array[] = { 1, 3, 5, 7, 9, 2, 4, 6, 8, 0, 1, 3, 5, 7, 9, 2, 4,
//6, 8, 0 };
//	set<int> s(array, array + sizeof(array) / sizeof(array));
//	cout << s.size() << endl;
//	// 正向打印set中的元素，从打印结果中可以看出：set可去重
//	for (auto& e : s)
//		cout << e << " ";
//	cout << endl;
//	// 使用迭代器逆向打印set中的元素
//	for (auto it = s.rbegin(); it != s.rend(); ++it)
//		cout << *it << " ";
//	cout << endl;
//	// set中值为3的元素出现了几次
//	cout << s.count(3) << endl;
//}

//#include <string>
//#include <map>
//void TestMap()
//{
//	map<string, string> m;
//	// 向map中插入元素的方式：
//	// 将键值对<"peach","桃子">插入map中，用pair直接来构造键值对
//	m.insert(pair<string, string>("peach", "桃子"));
//	// 将键值对<"peach","桃子">插入map中，用make_pair函数来构造键值对
//	m.insert(make_pair("banan", "香蕉"));
//
//	// 借用operator[]向map中插入元素
//	   /*
//	operator[]的原理是：
//	 用<key, T()>构造一个键值对，然后调用insert()函数将该键值对插入到map中
//	 如果key已经存在，插入失败，insert函数返回该key所在位置的迭代器
//	 如果key不存在，插入成功，insert函数返回新插入元素所在位置的迭代器
//	 operator[]函数最后将insert返回值键值对中的value返回
//	*/
//	// 将<"apple", "">插入map中，插入成功，返回value的引用，将“苹果”赋值给该引
//	用结果，
//		m["apple"] = "苹果";
//	// key不存在时抛异常
//	//m.at("waterme") = "水蜜桃";
//	cout << m.size() << endl;
//	// 用迭代器去遍历map中的元素，可以得到一个按照key排序的序列
//	for (auto& e : m)
//		cout << e.first << "--->" << e.second << endl;
//	cout << endl;
//	// map中的键值对key一定是唯一的，如果key存在将插入失败
//	auto ret = m.insert(make_pair("peach", "桃色"));
//	if (ret.second)
//		cout << "<peach, 桃色>不在map中, 已经插入" << endl;
//	else
//		cout << "键值为peach的元素已经存在：" << ret.first->first << "--->"
//		<< ret.first->second << " 插入失败" << endl;
//	// 删除key为"apple"的元素
//	m.erase("apple");
//	if (1 == m.count("apple"))
//		cout << "apple还在" << endl;
//	else
//		cout << "apple被吃了" << endl;
//}

//#include <set>
//void TestSet()
//{
//	int array[] = { 2, 1, 3, 9, 6, 0, 5, 8, 4, 7 };
//
//	// 注意：multiset在底层实际存储的是<int, int>的键值对
//	multiset<int> s(array, array + sizeof(array) / sizeof(array[0]));
//	for (auto& e : s)
//		cout << e << " ";
//	cout << endl;
//	return 0;
//}
//
//template <class K, class V>
//class AVLNode
//{
//public:
//	AVLNode(const pair<K, V>& kv)
//		: _kv(kv)
//		, _left(nullptr)
//		, _right(nullptr)
//		, _parent(nullptr)
//		, _bf(0)
//	{}
//
//	pair<K, V> _kv;
//	AVLNode<K, V>* _left;
//	AVLNode<K, V>* _right;
//	AVLNode<K, V>* _parent;
//	int _bf;
//};

/*
  上图在插入前，AVL树是平衡的，新节点插入到30的左子树(注意：此处不是左孩子)中，30左
子树增加
  了一层，导致以60为根的二叉树不平衡，要让60平衡，只能将60左子树的高度减少一层，右子
树增加一层，
  即将左子树往上提，这样60转下来，因为60比30大，只能将其放在30的右子树，而如果30有
右子树，右子树根的值一定大于30，小于60，只能将其放在60的左子树，旋转完成后，更新节点
的平衡因子即可。在旋转过程中，有以下几种情况需要考虑：
  1. 30节点的右孩子可能存在，也可能不存在
  2. 60可能是根节点，也可能是子树
     如果是根节点，旋转完成后，要更新根节点
     如果是子树，可能是某个节点的左子树，也可能是右子树
    
 同学们再此处可举一些详细的例子进行画图，考虑各种情况，加深旋转的理解
*/

int main()
{
	return 0;
}
